home *** CD-ROM | disk | FTP | other *** search
/ CD Actual 85 / CD Temático 40 Febrero 2004.iso / DOS / testdisk / src / ext2.c < prev    next >
Encoding:
C/C++ Source or Header  |  2004-01-09  |  6.5 KB  |  173 lines

  1. /*
  2.  
  3.     File: ext2.c
  4.  
  5.     Copyright (C) 1998-2004 Christophe GRENIER <grenier@cgsecurity.org>
  6.   
  7.     This software is free software; you can redistribute it and/or modify
  8.     it under the terms of the GNU General Public License as published by
  9.     the Free Software Foundation; either version 2 of the License, or
  10.     (at your option) any later version.
  11.   
  12.     This program is distributed in the hope that it will be useful,
  13.     but WITHOUT ANY WARRANTY; without even the implied warranty of
  14.     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  15.     GNU General Public License for more details.
  16.   
  17.     You should have received a copy of the GNU General Public License
  18.     along with this program; if not, write to the Free Software
  19.     Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  20.  
  21.  */
  22. #include <stdio.h>
  23. #include <string.h>
  24. #include "types.h"
  25. #include "common.h"
  26. #include "ext2.h"
  27. #include "intrface.h"
  28. #include "fnctdsk.h"
  29.  
  30. #define EXT2_BLOCK_SIZE(s)      (EXT2_MIN_BLOCK_SIZE << (s)->s_log_block_size)
  31. static int test_EXT2(t_param_disk *disk_car, const struct ext2_super_block *sb,t_diskext *partition,const int debug, const int dump_ind);
  32.  
  33. int check_EXT2(t_param_disk *disk_car,t_diskext *partition,const int debug)
  34. {
  35.   unsigned char buffer[8*SECTOR_SIZE];
  36.   if(disk_car->read(disk_car,8, &buffer, partition->lba)!=0)
  37.   { return 1; }
  38.   if(test_EXT2(disk_car,(struct ext2_super_block*)&buffer[0x400],partition,debug,0)!=0)
  39.     return 1;
  40.   set_EXT2_info(disk_car,(struct ext2_super_block*)&buffer[0x400],partition,debug,0);
  41.   return 0;
  42. }
  43.  
  44. int set_EXT2_info(t_param_disk *disk_car, const struct ext2_super_block *sb,t_diskext *partition,const int debug, const int dump_ind)
  45. {
  46.   partition->info[0]='\0';
  47.   set_part_name(partition,sb->s_volume_name,16);
  48.   /* sb->s_last_mounted seems to be unemployed in kernel 2.2.16 */
  49.   if(EXT2_HAS_COMPAT_FEATURE(sb,EXT3_FEATURE_COMPAT_HAS_JOURNAL)!=0)
  50.     strncpy(partition->info,"EXT3 ",sizeof(partition->info));
  51.   else
  52.     strncpy(partition->info,"EXT2 ",sizeof(partition->info));
  53.   if(EXT2_HAS_RO_COMPAT_FEATURE(sb,EXT2_FEATURE_RO_COMPAT_LARGE_FILE)!=0)
  54.     strcat(partition->info,"Large file ");
  55.   if(EXT2_HAS_RO_COMPAT_FEATURE(sb,EXT2_FEATURE_RO_COMPAT_SPARSE_SUPER)!=0)
  56.     strcat(partition->info,"Sparse superblock ");
  57.   if(EXT2_HAS_INCOMPAT_FEATURE(sb,EXT3_FEATURE_INCOMPAT_RECOVER)!=0)
  58.     strcat(partition->info,"Recover ");
  59.   if(EXT2_HAS_INCOMPAT_FEATURE(sb,EXT3_FEATURE_INCOMPAT_JOURNAL_DEV)!=0)
  60.     strcat(partition->info,"Journal dev ");
  61.   if(le16(sb->s_block_group_nr)!=0)
  62.   {
  63.     strcat(partition->info,"Backup superblock ");
  64.     if(debug!=0)
  65.     {
  66.       ecrit_rapport("\nblock_group_nr %u\n",le16(sb->s_block_group_nr));
  67.     }
  68.   }
  69.   /* last mounted => date */
  70.   return 0;
  71. }
  72.  
  73. /*
  74. Primary superblock is at 1024 (SUPERBLOCK_OFFSET)
  75. Group 0 begin at s_first_data_block
  76. */
  77. int recover_EXT2(t_param_disk *disk_car, const struct ext2_super_block *sb,t_diskext *partition,const int debug, const int dump_ind)
  78. {
  79.   if(test_EXT2(disk_car,sb,partition,debug,dump_ind)!=0)
  80.     return 1;
  81.   set_EXT2_info(disk_car,sb,partition,debug,dump_ind);
  82.   partition->part_type=(unsigned char)P_LINUX;
  83.   partition->part_size=le32(sb->s_blocks_count)*(EXT2_MIN_BLOCK<<le32(sb->s_log_block_size));
  84.   partition->boot_sector=le16(sb->s_block_group_nr)*le32(sb->s_blocks_per_group);
  85.   partition->boot_sector=0;
  86.   partition->blocksize=EXT2_MIN_BLOCK_SIZE<<le32(sb->s_log_block_size);
  87.   if(le16(sb->s_block_group_nr)>0)
  88.   {
  89.     partition->lba-=(le32(sb->s_first_data_block)+le16(sb->s_block_group_nr)*le32(sb->s_blocks_per_group))*(EXT2_MIN_BLOCK<<le32(sb->s_log_block_size));
  90.   }
  91.   if(debug!=0)
  92.   {
  93.     ecrit_rapport("\nrecover_EXT2: s_block_group_nr=%u/%u, s_mnt_count=%u/%d, s_blocks_per_group=%u\n",
  94.     le16(sb->s_block_group_nr), le32(sb->s_blocks_count)/le32(sb->s_blocks_per_group), le16(sb->s_mnt_count),le16(sb->s_max_mnt_count),le32(sb->s_blocks_per_group));
  95.     ecrit_rapport("recover_EXT2: boot_sector=%lu, s_blocksize=%lu\n",partition->boot_sector,partition->blocksize);
  96.     ecrit_rapport("recover_EXT2: s_blocks_count %u\n",le32(sb->s_blocks_count));
  97.     ecrit_rapport("recover_EXT2: part_size %lu\n",partition->part_size);
  98.     /*
  99.     {
  100.       unsigned char buffer2[2*SECTOR_SIZE];
  101.       unsigned int group;
  102.       group=1;
  103.       while(group<=9)
  104.       {
  105.     dword hd_offset=partition->lba+(le32(sb->s_first_data_block)+group*le32(sb->s_blocks_per_group))*(EXT2_MIN_BLOCK<<le32(sb->s_log_block_size));
  106.     ecrit_rapport("%lu+(%u+%u*%u)*%u\n",partition->lba,le32(sb->s_first_data_block),group,le32(sb->s_blocks_per_group),(EXT2_MIN_BLOCK<<le32(sb->s_log_block_size)));
  107.     ecrit_rapport("Group %u Backup superblock at %u (LBA=%lu) ",group,group*le32(sb->s_blocks_per_group),hd_offset);
  108.     if(disk_car->read(disk_car,2, buffer2, hd_offset)==0)
  109.     {
  110.       const struct ext2_super_block *sb2=(const struct ext2_super_block*)&buffer2;
  111.       unsigned int res=test_EXT2(disk_car,sb2,partition,debug,dump_ind);
  112.       if(res==0)
  113.       {
  114.         ecrit_rapport("Ok\n");
  115.       }
  116.       else
  117.       {
  118.         ecrit_rapport("Bad res=%u\n",res);
  119.       }
  120. //      dump(stdscr,buffer2,2*SECTOR_SIZE);
  121.     }
  122.     if(group==0)
  123.       group=1;
  124.     else if(group==1)
  125.       group=3;
  126.     else if(group==3)
  127.       group=5;
  128.     else if(group==5)
  129.       group=7;
  130.     else if(group==7)
  131.       group=9;
  132.     else
  133.       group=11;
  134.       }
  135.  
  136.     }
  137.     */
  138.   }
  139. return 0;
  140. }
  141.  
  142. static int test_EXT2(t_param_disk *disk_car, const struct ext2_super_block *sb,t_diskext *partition,const int debug, const int dump_ind)
  143. {
  144.   if(le16(sb->s_magic)!=EXT2_SUPER_MAGIC)
  145.     return 1;
  146.   if(dump_ind!=0)
  147.   {
  148.     ecrit_rapport("\nLinux magic value at %u/%u/%u\n", LBA2cylinder(disk_car,partition->lba),LBA2head(disk_car,partition->lba),LBA2sector(disk_car,partition->lba));
  149.     /* There is a little offset ... */
  150.     dump(stdscr,sb,SECTOR_SIZE);
  151.   }
  152.   if (le32(sb->s_free_blocks_count) >= le32(sb->s_blocks_count)) return 2;
  153.   if (le32(sb->s_free_inodes_count) >= le32(sb->s_inodes_count)) return 3;
  154.   if (le16(sb->s_errors)!=0 &&
  155.       (le16(sb->s_errors) != EXT2_ERRORS_CONTINUE) &&
  156.       (le16(sb->s_errors) != EXT2_ERRORS_RO) &&
  157.       (le16(sb->s_errors) != EXT2_ERRORS_PANIC))
  158.     return 5;
  159.   if ((le16(sb->s_state) & ~(EXT2_VALID_FS | EXT2_ERROR_FS))!=0)
  160.     return 5;
  161.   if (le32(sb->s_blocks_count) == 0) /* reject empty filesystem */
  162.     return 6;
  163.   if(le32(sb->s_log_block_size)>2)  /* block size max = 4096, can be 8192 on alpha */
  164.     return 7;
  165.   if(partition->part_size!=0 && (partition->part_size<le32(sb->s_blocks_count)*(EXT2_MIN_BLOCK<<le32(sb->s_log_block_size))))
  166.     return 8;
  167.   if(EXT2_HAS_COMPAT_FEATURE(sb,EXT3_FEATURE_COMPAT_HAS_JOURNAL)!=0)
  168.     partition->upart_type=UP_EXT3;
  169.   else
  170.     partition->upart_type=UP_EXT2;
  171.   return 0;
  172. }
  173.